<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2023/8/18
 * Time: 11:15
 */

namespace app\logic\cron;


use app\common\lib\Common;
use app\common\lib\Guzzle;
use app\common\lib\GuzzleNew;
use app\common\lib\TencentCos;
use app\exception\IndexException;
use app\logic\BaseLogic;
use app\model\novel\NovelChapterModel;
use app\model\novel\NovelChapterPartModel;
use app\model\novel\NovelSpreadModel;
use app\model\novel\NovelSpreadUnderWaterModel;
use app\model\overseas\HinovelDataModel;
use support\Cache;
use support\Db;
use support\Redis;
use Webman\Util;

class HinovelLogic extends BaseLogic
{
    protected $client_id = 'T001101';
    protected $client_secret = 'QJuOqXhKd24fJf-0WD3bVoxfLjRf6efc60QE_tGivUK0Ye10Zu0v4zlFgsuB0LvA';
    static $url = [
        'https://tui.hinovelasia.com/',
        'https://tui.hinoveleurope.com/',
    ];
    static $langMap = [];

    protected static $instance;

    protected $insertTaskDatas;

    public function __construct()
    {
        self::$langMap = [
            'en'=>self::$url[0],
            'vi'=>self::$url[0],
            'id'=>self::$url[0],
            'th'=>self::$url[0],
            'ko'=>self::$url[0],

//            'ru'=>self::$url[1],
//            'fr'=>self::$url[1],
//            'es'=>self::$url[1],
//            'pt'=>self::$url[1],
//            'de'=>self::$url[1],
//            'it'=>self::$url[1],
        ];
        parent::__construct();
    }

    public static function getInstance()
    {
//        if (is_object(self::$instance)) {
//            return self::$instance;
//        }

        return  new self();
    }

    protected function getAccessToken()
    {
        $token = Redis::connection('common')->get('hinovel_access_token');
        if($token){
            return $token;
        }

        $param = [
            'client_id'=>$this->client_id,
            'client_secret'=>$this->client_secret,
        ];
        $result = (new GuzzleNew())->post(self::$url[0],'oauth2/token.json',$param);
        if(!empty($result['data']['access_token'])){
            Redis::connection('common')->setex('hinovel_access_token',3600,$result['data']['access_token']);
            return $result['data']['access_token'];
        }
        throw new IndexException(4020,'获取token失败');
    }

    public function getNovelList()
    {
        foreach (self::$langMap as $lang=>$url){
            $this->getHinovelList($lang,$url,1);
            sleep(1);
        }

        return ['success'];
    }

    public function getHinovelList($lang,$url,$page=1)
    {
        $businessId = 1000;
        $limit = 100;
        $token = $this->getAccessToken();
        $param = [
            'page'=>$page,
            'limit'=>$limit,
        ];
        $header = [
            'Authorization'=>'Bearer '.$token,
            'client-id'=>$this->client_id,
            'lang'=>$lang,
            'nonce'=>Common::randString(8),
            'timestamp'=>time(),
        ];
        $path = 'book/list.json?'.http_build_query($param);
        $result = (new GuzzleNew())->get($url,$path,$header);
        if(!empty($result['data'])){
            foreach($result['data']['list'] as $val){
                $val['lang'] = $lang;

                $this->autoCreateTableAndInsertData(
                    [
                        'table'=>'video_hinovel_novel_data',
                        'keyid'=>'id',
                        'update_fields'=>['book_no'],
                        'attributes'=>$val
                    ]
                );

                $allow_column = false;
                try{
                    $allow_column = \plugin\admin\app\common\Util::db()->select("desc `video_hinovel_novel_data_chapter`");
                }catch (\Throwable $e){}

                $count = 0;
                if ($allow_column) {
                    $count = Db::table('video_hinovel_novel_data_chapter')->where('book_no',$val['book_no'])->count();
                }

                if($allow_column==false || $count==false){
                    $param = [
                        'book_no'=>$val['book_no'],
                    ];
                    $path = 'book/details.json?'.http_build_query($param);
                    $chapters = (new GuzzleNew())->get($url,$path,$header);
                    if(!empty($chapters['data'])){
                        foreach($chapters['data']['chapters'] as $chapter){
                            $chapter['name'] = $chapters['data']['name'];
                            $chapter['book_no'] = $chapters['data']['book_no'];
                            $this->autoCreateTableAndInsertData(
                                [
                                    'table'=>'video_hinovel_novel_data_chapter',
                                    'keyid'=>'id',
                                    'update_fields'=>['book_no','title'],
                                    'attributes'=>$chapter
                                ]
                            );
                        }

                        //todo 插入小说数据
                        $novel = NovelSpreadModel::getInstance()->getWhere(['book_id'=>$val['book_no'],'isdel'=>0])->count();
                        if($novel==false){
                            $mainImageFileName = substr(md5(uniqid().time()),-26).'.jpg';
                            try{
                                $res = TencentCos::getInstance()->uploadLocalFile($val['cover'],'hinovel/novel',$mainImageFileName);
                                if(isset($res['Location'])){
                                    $mainImage = 'https://'.$res['Location'];
                                }
                            }catch (\Exception $e){}

                            $maxId =  NovelSpreadModel::getInstance()->getWhere([['novel_sn','>',0]])->max('novel_sn');
                            $novelSn = Common::getSnCode($maxId,'50',3,1);
                            $insert = [
                                'novel_sn'=>$novelSn,
                                'title'=>$val['name']??'',
                                'main_image'=>$mainImage??'',
                                'business_id'=>$businessId,
                                'labels'=>$val['book_label'],
                                'desc'=>$val['intro'],
                                'data_source_key'=>HinovelDataModel::getInstance()->getTable(),
                                'data_source_id'=>$val['book_no'],
                                'start_time'=>date('Y-m-d H:i:s'),
                                'author'=>$val['author'],
                                'book_id'=>$val['book_no'],
                                'lang'=>$val['lang'],
                                'status'=>0,
                                'spread_type'=>3,
                                'platform'=>5,
                                'is_end'=>$val['status']==1?1:0,
                            ];
                            $id = NovelSpreadModel::getInstance()->saveData($insert);

                            foreach($chapters['data']['chapters'] as $k=>$chapter){
                                $contents = explode("\n",$chapter['content']);
                                $contents = array_slice($contents,0,300);
                                $insert2 = [
                                    'novel_sn'=>$novelSn,
                                    'number'=>($k+1),
                                    'name'=>$chapter['title'],
                                    'original_content'=>implode("\n",$contents),
                                    'spread_type'=>3,
                                    'lang'=>$val['lang'],
                                ];
                                NovelChapterModel::getInstance()->insert($insert2);
                            }
                        }
                    }
                }
            }
            if($result['data']['total']>round($page*$limit)){
                usleep(10000);
                $page++;
                $this->getHinovelList($lang,$url,$page);
            }
        }

        return ['success'];
    }

    /**
     *  获取口令
     * @param $userSn
     * @param $bookNo
     * @param $lang
     * @return mixed
     * @throws IndexException
     */
    public function getPasswordCode($userSn,$bookNo,$lang)
    {
        $url = self::$langMap[$lang]??self::$url[0];
        $param = [
            'book_no'=>$bookNo,
            'user_no'=>$userSn,
        ];

        $token = $this->getAccessToken();

        $header = [
            'Authorization'=>'Bearer '.$token,
            'client-id'=>$this->client_id,
            'lang'=>$lang,
            'nonce'=>Common::randString(8),
            'timestamp'=>time(),
        ];
        //var_dump($header);
        $result = (new GuzzleNew())->post($url,'book/getCode.json',$param,$header);
        if(!empty($result['data']['code'])){
            return $result['data']['code'];
        }
        //var_dump($header,$param,$result);
        throw new IndexException(4020,'获取口令失败');
    }

    public function getOrderList()
    {
        $days = [0,1,2,3];
        foreach($days as $day){
            $date = date('Y-m-d',strtotime('- '.$day.'day'));
            foreach (self::$langMap as $lang=>$url){
                $this->getOrderData($lang,$url,$date);
                sleep(1);
            }
        }

        return ['success'];
    }

    protected function getOrderData($lang,$url,$date,$page=1)
    {
        $limit = 100;
        $token = $this->getAccessToken();
        $param = [
            'date'=>$date,
            'page'=>$page,
            'limit'=>$limit,
        ];
        $header = [
            'Authorization'=>'Bearer '.$token,
            'client-id'=>$this->client_id,
            'lang'=>$lang,
            'nonce'=>Common::randString(8),
            'timestamp'=>time(),
        ];
        $path = 'book/getOrder.json?'.http_build_query($param);
        $result = (new GuzzleNew())->get($url,$path,$header);
        //var_dump($result,(new GuzzleNew())->getError());
        if(!empty($result['data'])) {
            foreach ($result['data']['list'] as $val) {
                $this->autoCreateTableAndInsertData(
                    [
                        'table'         => 'video_hinovel_order_data',
                        'keyid'         => 'id',
                        'update_fields' => ['order_no'],
                        'attributes'    => $val
                    ]
                );
            }
            if($result['data']['total']>round($page*$limit)){
                usleep(10000);
                $page++;
                $this->getOrderData($lang,$url,$date,$page);
            }
        }
    }

    /**
     * 定时ai分析原文内容并更新分析内容-提前准备
     * @return array
     * @throws IndexException
     */
    public function getChapterContent()
    {
        $where = [
            'isdel'=>0,
            'spread_type'=>3,
            'lang'=>'en',
            ['original_content','<>',''],
        ];
        $datas = NovelChapterModel::getInstance()->getWhere($where)->whereNull('content')->orderBy('status','desc')->limit(100)->get();
        $cmd = getAiCommand('original_content_ai_command_overseas');
        foreach($datas as $val){
            $contentText = $val['original_content'];
            $content = Common::generatedContent($contentText,$cmd,$val['lang']);
            $contents = array_values(array_filter(explode("\n",$content)));
            foreach ($contents as $k=>$content){
                //内容必须包含字母或数字，不能只有符号
                if(preg_match('/[a-z|A-Z|0-9]+/',$content)==false){
                    unset($contents[$k]);
                }
            }
            $val->content = implode("\n",array_values($contents));
            $val->save();
        }
        return ['success'];
    }

    public function getCooperateLink($keyword,$lang)
    {
        $url = self::$langMap[$lang]??self::$url[0];
        $param = [
            'code'=>$keyword,
        ];

        $token = $this->getAccessToken();

        $header = [
            'Authorization'=>'Bearer '.$token,
            'client-id'=>$this->client_id,
            'lang'=>$lang,
            'nonce'=>Common::randString(8),
            'timestamp'=>time(),
        ];
        //var_dump($header);
        $result = (new GuzzleNew())->post($url,'book/getLink.json',$param,$header);
        if(!empty($result['data']['link'])){
            return $result['data']['link'];
        }
        //var_dump($header,$param,$result);
        //throw new IndexException(4020,'获取深度链接失败');
        return '';
    }
}